Linux: O graceful shutdown

==== OpenCPN and Linux powerup/down management updated for Ubuntu 20.04 and OpenCPN 5.6.0.

Note thar this is currently a 'work in progress', give me a few days to get done. ====

Problem

I've been struggling to find a solution to the problem where OpenCPN shuts down 'violently' instead of gratefulas.

In Linux this is not an OpenCPN problem but is related to systemd so I looked for a correct start/stop procedure as published here.

Starting and stopping OpenCPN on a dedicated system with Ubuntu 20.04 using Xfce and lightdm-gtk-greeter.

The machine used is a 'Car-PC' with an M2-ATX power supply but should be applicable om most systems where a 'Power button' (or switch), is used for start and stop.

Prerequisites:

Systemd is, since Ubuntu 15.04, the default method starting and stopping system and applications. Systemd simply assumes that all running applications are closed at the instant a 'SIGTERM' is sent to the application causing programs like OpenCPN being closed not given time to save configuration files or log files.

First:

OpenCPN shall be run by a dedicated user (not root!) and should, by systemd, be run as that user. This option is badly supported due to the lack of support for graphical shells using targets and services. The method used here will, as there is only one (automatically logged in) user on the system, serve the same purpose. OpenCPN is also run in the background not to affect the GUI as much.

Enable automatic login:

  [SeatDefaults]
  autologin-user=<user>

Modify systemd settings:

 sudo loginctl enable-linger <user>

* Allow user processes to be run after the user has logged out, use 'sudo' and update '/etc/systemd/logind.conf' removing the hashmark for 'KillUserProcesses=no'. Do NOT remove the hashmark for any of the 'Handle' options.

Start script for OpenCPN:

-----------------
#!/bin/bash

systemd-inhibit --what=handle-power-key --mode=block /usr/bin/opencpn &

exit 0
-----------------

Enable systemd to start OpenCPN:

-----------------
[Unit]
Description=opencpn
After=display-manager.service lightdm.service graphical.target
Conflicts=exit.target shutdown.target reboot.target halt.target

[Service]
Type=oneshot
User=<user>
Group=<user>
RemainAfterExit=yes
ExecStartPre=logger Starting OpenCPN Service
# Allow time for GUI to start properly
ExecStartPre=sleep 6
Environment=DISPLAY=:0.0
Environment=Xauthority=/home/<user>/.Xauthority
# The systemd-inhibit function need be in a separate script
ExecStartPre=logger Starting OpenCPN startscript
ExecStart=/usr/local/bin/ocpnStart.sh
ExecStop=logger Shutting down OpenCPN
ExecStop=pkill -15 opencpn
ExecStopPost=logger Kill command sent
ExecStopPost=sleep 5

[Install]
WantedBy=graphical.target
-----------------

You may also see a number of ALSA messages, these are another story an can be safely ignored.

Shutting down OpenCPN gracefully:

button/power PBTN 00000080 00000000
button/power LNXPWRBN:00 00000080 00000001
button/power PBTN 00000080 00000000
button/power LNXPWRBN:00 00000080 00000002
  -----------------
  #!/bin/bash
  # /etc/acpi/powerbtn.sh
  # Initiates a shutdown when power button has been pressed

  # Shutdown OpenCPN
  sudo systemctl stop opencpn.service

  # Shutdown the whole system
  shutdown -h now
  -----------------

A bonus addition: Shutting down thru Xfce:

  -----------------
  #!/bin/bash

  wmctrl -c opencpn
  sleep 1
  /usr/bin/xfce4-session-logout -h

  exit 0
  -----------------

That should be all. Enjoy! Hope this explains my view on what is happening and can be of use to you

Best Regards [LennartG] Lennart Gilander

Addendum

MaVi writes:

Well, first I misread what the line

<Code> sudo sed -e '/shutdown/ s/^#*/#/' -i /etc/rc.local

actually does, which explained why I could not find the trigger for the script. It is triggered at boot time.. So I created a simple script from the graceful shutdown page , basically:

#!/bin/bash
# /etc/acpi/powerbtn.sh
# Initiates a shutdown when power button has been
# pressed
LOGFILE=/home/pi/shutdownlog.log
$USER=pi

echo '$(date) OCPN stop request received'>> $LOGFILE
if /usr/bin/pgrep -u $USER opencpn> /dev/null ; then
  echo '$(date) OCPN found running. Stopping now'>> $LOGFILE
  /usr/bin/pkill -u $USER opencpn
fi
while (pgrep -x opencpn>/dev/null); do
  sleep 1
  echo '$(date) Waiting for OCPN to stop'>> $LOGFILE
done
echo '$(date) OCPN stopped'>> $LOGFILE
sleep 2

as killOCPN.sh (and of course chmod +x'ed) Next I added the killOPCN command into the /etc/x710pwr.sh script , just before the 'sudo poweroff' and 'sudo reboot' lines.

The one thing I haven't figured out yet is how to use a simple shutdown button press insted of the long press that is now required- I can shorten the rebootpulsemaximum, but then the X710 does not power-off, but that's for the next rainy sunday afternoon…